package com.broker.consumer.controller;

import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import me.send.broker.entity.WithdrawOrder;
import me.send.broker.entity.base.ReturnBean;
import me.send.broker.pojo.AliWithdrawReturnRecord;
import me.send.broker.pojo.WithdrawRecordBean;
import me.send.broker.service.WalletService;
import me.send.business.base.alipay.config.AlipayConfig;
import me.send.business.base.alipay.util.AlipayNotify;
import me.send.business.base.alipay.util.AlipaySubmit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.broker.consumer.controller.base.BaseController;

@Controller
@RequestMapping(value = "/wallet")
public class WalletController extends BaseController {
	private final static Logger logger = LoggerFactory
			.getLogger(WalletController.class.getName());
	public final int WITHDRAW_STATUS_PROCESSING = 0;//表示处理中，未审核
	public final int WITHDRAW_STATUS_HAD_AUTH = 1;//表示已审核
	private final double AUTO_AUTH_AMOUNT = 5000d;//低于5000自动审核
	/**
	 * 经纪人申请提现接口
	 * 
	 * @param popid
	 * @param num
	 * @param type
	 * @param accountNum
	 * @return
	 */
	@RequestMapping("/withdraw")
	@ResponseBody
	public ReturnBean withdraw(int popid, double num, int type,
			String accountNum,String realName) {
		ReturnBean returnBean = new ReturnBean();
		Double balance = walletService.allTotal(popid);
		if (num<=0||num > balance||balance<=0) {// 提现金额超过可取余额
			returnBean.setCode(1);
			returnBean.setMessage("可取余额不足，请重新输入");
			return returnBean;
		} else {
			WithdrawRecordBean wr = new WithdrawRecordBean();
			wr.setType(type);
			wr.setAccountNumber(accountNum);
			wr.setNum(num);
			wr.setPopid(popid);
			wr.setWithdrawOrderNo("HSWD"+dateFormat("yyyyMMddHHmmss", new Date())+popid);
			wr.setCreateTime(dateFormat("yyyy-MM-dd HH:mm:ss", new Date()));
			wr.setBrokerName(realName);
			if(num>=AUTO_AUTH_AMOUNT){
				wr.setStatus(WITHDRAW_STATUS_PROCESSING);//5000及以上的需财务在后台手动审核
			}else{
				wr.setStatus(WITHDRAW_STATUS_HAD_AUTH);//小于5000的提现自动审核通过
			}
			walletService.buildRecord(wr);// 生成提现记录
//			walletService.withdrawInvoke(wr);// 触发动作 此处数据库操作需保证在一个事务里 因此此逻辑迁移到生成提现记录里
			returnBean.setCode(0);
			returnBean.setMessage("提现请求已经提交，请耐心等待");
		}
		return returnBean;
	}
	
	private String dateFormat(String pattern,Date date){
		SimpleDateFormat sdf = new SimpleDateFormat(pattern);
		return sdf.format(date);
	}

	/**
	 * 经纪人钱包各项数据明细
	 */
	@RequestMapping("/myWallet")
	@ResponseBody
	public Map<String, Object> myWallet(int popid) {
		Map<String, Object> details = walletService.myWallet(popid);
		Map<String, Object> result = new HashMap<String, Object>();
		result.put("code", 0);
		result.put("message", "success");
		result.put("datas", details);
		return result;
	}

	/**
	 * 经纪人所有记录明细
	 */
	@RequestMapping("/details")
	@ResponseBody
	public Map<String, Object> details(int popid, String type, int size,
			int lastid) {
		double sum = 0;// 总额
		int pageNum = 0;// 页数
		Map<String, Object> m = new HashMap<String, Object>();
		m.put("popid", popid);
		m.put("type", type);
		m.put("size", size);
		m.put("lastId", lastid);
		List<Map<String, Object>> details = new ArrayList<Map<String, Object>>();// 列表
		if (type.equals("tip")) {// 小费总额明细
			details = walletService.chargeInDetails(m);
			sum = walletService.chargeInTotal(popid);
			pageNum = walletService.chargeInPage(m);
		} else if (type.equals("buy")) {// 代购总额明细
			details = walletService.buyDetails(m);
			sum = walletService.buyTotal(popid);
			pageNum = walletService.buyPage(m);
		} else if (type.equals("balance")) {// 可用余额明细
			details = walletService.allDetails(m);
			sum = walletService.allTotal(popid);
			pageNum = walletService.allPage(m);
		} else if (type.equals("withdraw")) {// 提现申请明细
			details = walletService.withdrawDetails(m);
			sum = walletService.inWithdraw(popid);
			pageNum = walletService.withdrawPage(m);
		} else {
			details = null;
		}
		Map<String, Object> result = new HashMap<String, Object>();
		result.put("code", 0);
		result.put("message", "success");
		result.put("datas", details);
		result.put("sum", sum);
		result.put("pagenum", pageNum);
		return result;
	}
	
	private String time(String pattern) {
		SimpleDateFormat sdf = new SimpleDateFormat(pattern);
		return sdf.format(new Date());
	}
	
	@RequestMapping("/request/alipay/batch")
	@ResponseBody
	public String requestAliBatchPay(HttpServletRequest request) throws Exception{
		////////////////////////////////////请求参数//////////////////////////////////////
		
		//服务器异步通知页面路径
		String notify_url = "http://www.yihusong.com/brokerConsumer/wallet/broker/alipay/batch/notify_url";
		//需http://格式的完整路径，不允许加?id=123这类自定义参数
		
		//付款账号
		String email = "yihusong@163.com";
		//必填
		
		//付款账户名
		String account_name = "南京呼送电子科技有限公司";
		//必填，个人支付宝账号是真实姓名公司支付宝账号是公司名称
		
		SimpleDateFormat sdf =new SimpleDateFormat("yyyyMMdd");
		String currentDay=sdf.format(new Date());
		//付款当天日期
		String pay_date = currentDay;
		//必填，格式：年[4位]月[2位]日[2位]，如：20100801
		
		//批次号
		String batch_no = "201509051553270";
		//必填，格式：当天日期[8位]+序列号[3至16位]，如：201008010000001
		
		//付款总金额
		String batch_fee = "0.01";
		//必填，即参数detail_data的值中所有金额的总和
		
		//付款笔数
		String batch_num = "1";
		//必填，即参数detail_data的值中，“|”字符出现的数量加1，最大支持1000笔（即“|”字符出现的数量999个）
		
		//付款详细数据
		String detail_data = "20150905153512^13043491757^金聪敏^0.01^经纪人提现";
		//必填，格式：流水号1^收款方帐号1^真实姓名^付款金额1^备注说明1|流水号2^收款方帐号2^真实姓名^付款金额2^备注说明2....
		
		
		//////////////////////////////////////////////////////////////////////////////////
		
		//把请求参数打包成数组
		Map<String, String> sParaTemp = new HashMap<String, String>();
		sParaTemp.put("service", "batch_trans_notify");
		sParaTemp.put("partner", AlipayConfig.partner);
		sParaTemp.put("_input_charset", AlipayConfig.input_charset);
		sParaTemp.put("notify_url", notify_url);
		sParaTemp.put("email", email);
		sParaTemp.put("account_name", account_name);
		sParaTemp.put("pay_date", pay_date);
		sParaTemp.put("batch_no", batch_no);
		sParaTemp.put("batch_fee", batch_fee);
		sParaTemp.put("batch_num", batch_num);
		sParaTemp.put("detail_data", detail_data);
		
		//建立请求
		String sHtmlText = AlipaySubmit.buildRequest(sParaTemp,"get","确认");
		return sHtmlText;
	}
	
	@RequestMapping("/gen/beforeTw")
	@ResponseBody
	public String genBatchWithdrawOrderBefore12(){
		final String pattern="yyyy-MM-dd 12:00:00";
		new Thread(new Runnable() {
		public void run() {
			logger.info("生成批量付款订单入参，pattern：{}",pattern);
			String time=time(pattern);
			int count =walletService.queryWithdrawOrderCount(time);
			int n = (count/WalletService.BATCH_NUM)+1;//每100笔生成一笔批量付款订单
			for(int i=0;i<n;i++){
				String batchOrderNo = time("yyyyMMddHHmmss")+i;
				try {
					walletService.genBatchWithdrawOrder(batchOrderNo,pattern);
				} catch (Exception e) {
					n++;
					continue;
				}
			}
			logger.info("生成批量付款订单岀参，count：{}",count);
		}
	}).start();
		
		return "success";
	}
	
	@RequestMapping("/gen/afterTw")
	@ResponseBody
	public String genBatchWithdrawOrderAfter12(){
		final String pattern="yyyy-MM-dd 00:00:00";
		new Thread(new Runnable() {
		public void run() {
			logger.info("生成批量付款订单入参，pattern：{}",pattern);
			String time=time(pattern);
			int count =walletService.queryWithdrawOrderCount(time);
			int n = (count/WalletService.BATCH_NUM)+1;//每100笔生成一笔批量付款订单
			for(int i=0;i<n;i++){
				String batchOrderNo = time("yyyyMMddHHmmss")+i;
				try {
					walletService.genBatchWithdrawOrder(batchOrderNo,pattern);
				} catch (Exception e) {
					n++;
					continue;
				}
			}
			logger.info("生成批量付款订单岀参，count：{}",count);
		}
	}).start();
		return "success";
	}


	/**
	 * 支付宝支付回调接口
	 * 
	 * @param request
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("rawtypes")
	@RequestMapping(value="/broker/alipay/batch/notify_url", method = RequestMethod.POST)
	public void alipayBatchNotify(HttpServletRequest request,HttpServletResponse response) {
		logger.info("alipay_notify:begin"+request.getParameterMap());
		//获取支付宝POST过来反馈信息
		Map<String,String> params = new HashMap<String,String>();
		Map requestParams = request.getParameterMap();
		for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
			String name = (String) iter.next();
			String[] values = (String[]) requestParams.get(name);
			String valueStr = "";
			for (int i = 0; i < values.length; i++) {
				valueStr = (i == values.length - 1) ? valueStr + values[i]
						: valueStr + values[i] + ",";
			}
			//乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
			//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
			params.put(name, valueStr);
		}
		logger.info("alipay_notify:params"+params);
		
		PrintWriter out = null;
		try {
			out = response.getWriter();
		} catch (IOException e1) {
			logger.info("alipay_notify:fail"+e1);
			e1.printStackTrace();
		}
		
		//获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
		//批量付款数据中转账成功的详细信息

		String success_details=null;
		//批次号
		String batch_no=null;
		//回调ID
		String notify_id=null;
		//批量付款数据中转账失败的详细信息
		String fail_details=null;
		try {
			String success_detail=request.getParameter("success_details");
			if(success_detail!=null){
				success_details = new String(success_detail.getBytes("ISO-8859-1"),"UTF-8");
			}
			batch_no = new String(request.getParameter("batch_no").getBytes("ISO-8859-1"),"UTF-8");
			notify_id = new String(request.getParameter("notify_id").getBytes("ISO-8859-1"),"UTF-8");
			String faildetail=request.getParameter("fail_details");
			if(faildetail!=null){
				fail_details = new String(faildetail.getBytes("ISO-8859-1"),"UTF-8");
			}
		} catch (Exception e) {
			e.printStackTrace();
			logger.info("alipay_notify:fail"+e);
			out.println("fail");
			return;
		}

		//获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//

		if(AlipayNotify.verify(params)){//验证成功
			//////////////////////////////////////////////////////////////////////////////////////////
			//请在这里加上商户的业务逻辑程序代码
			List<WithdrawOrder> orders=walletService.queryAliWithdrawOrdersByBatchOrderNo(batch_no);
			
			Map<String,WithdrawOrder> orderMap=new HashMap<String, WithdrawOrder>();
			for(WithdrawOrder order:orders){
				orderMap.put(order.getWithdrawOrderNo(), order);
			}
			try {
			if(success_details!=null){
				List<AliWithdrawReturnRecord> successRecords=analysisAliWithdrawReturnRecode(success_details);
				Map<String,WithdrawOrder> successMap=new HashMap<String, WithdrawOrder>();
				for(AliWithdrawReturnRecord successRecord:successRecords){
					WithdrawOrder order=orderMap.get(successRecord.getWithdrawOrderNo());
					if(order!=null){
						order.setReason(successRecord.getRemark());
						successMap.put(successRecord.getWithdrawOrderNo(), order);
					}
				}
				walletService.dealWithSuccessAliBatchWithdrawResult(successMap, batch_no, notify_id);
			}
			if(fail_details!=null){
				List<AliWithdrawReturnRecord> failRecords=analysisAliWithdrawReturnRecode(fail_details);
				Map<String,WithdrawOrder> failMap=new HashMap<String, WithdrawOrder>();
				for(AliWithdrawReturnRecord failRecord:failRecords){
					WithdrawOrder order=orderMap.get(failRecord.getWithdrawOrderNo());
					if(order!=null){
						order.setReason(failRecord.getRemark());
						failMap.put(failRecord.getWithdrawOrderNo(), order);
					}
				}
				walletService.dealWithFailAliBatchWithdrawResult(failMap, batch_no, notify_id);
			}
			
				logger.info("alipay_notify:success");
				out.println("success");
				return;
			} catch (Exception e) {
				logger.info("alipay_notify:fail"+e);
				out.println("fail");
				return;
			}
			

			//——请根据您的业务逻辑来编写程序（以下代码仅作参考）——
			
			//判断是否在商户网站中已经做过了这次通知返回的处理
				//如果没有做过处理，那么执行商户的业务程序
				//如果有做过处理，那么不执行商户的业务程序
				
//			return "success";//请不要修改或删除

			//——请根据您的业务逻辑来编写程序（以上代码仅作参考）——

			//////////////////////////////////////////////////////////////////////////////////////////
		}else{//验证失败
			logger.info("alipay_notify:fail verify");
			out.println("fail");
			return;
		}
		
		
		
	}
	
	private List<AliWithdrawReturnRecord> analysisAliWithdrawReturnRecode(String return_details){
		String[] details=return_details.split("\\|");
		List<AliWithdrawReturnRecord> records=new ArrayList<AliWithdrawReturnRecord>();
		SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMddHHmmss");
		for(String detail:details){
			String[] detailArr=detail.split("\\^");
			AliWithdrawReturnRecord record=new AliWithdrawReturnRecord();
			record.setWithdrawOrderNo(detailArr[0]);
			record.setWithdrawAccountNo(detailArr[1]);
			record.setUserName(detailArr[2]);
			record.setAmount(new BigDecimal(detailArr[3]));
			record.setFlag(detailArr[4]);
			record.setRemark(detailArr[5]);
			record.setAliOrderNo(detailArr[6]);
			Calendar finishTime=Calendar.getInstance();
			try {
				finishTime.setTime(sdf.parse(detailArr[7]));
			} catch (ParseException e) {
			}
			record.setFinishTime(finishTime);
			records.add(record);
		}
		return records;
	}
	

	
	public static void main(String[] args) throws Exception {
		
		
		
//		String success_details ="001^jcm@163.com^金聪敏^20.00^S^null^200810248427067^20150827094230|002^zc@163.com^周宠^100.00^S^null^200810248427068^20150827094231";
//		String[] details=success_details.split("\\|");
//		List<AliWithdrawReturnRecord> records=new ArrayList<AliWithdrawReturnRecord>();
//		SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMddHHmmss");
//		for(String detail:details){
//			String[] detailArr=detail.split("\\^");
//			AliWithdrawReturnRecord record=new AliWithdrawReturnRecord();
//			record.setWithdrawOrderNo(detailArr[0]);
//			record.setWithdrawAccountNo(detailArr[1]);
//			record.setUserName(detailArr[2]);
//			record.setAmount(new BigDecimal(detailArr[3]));
//			record.setFlag(detailArr[4]);
//			record.setRemark(detailArr[5]);
//			record.setAliOrderNo(detailArr[6]);
//			Calendar finishTime=Calendar.getInstance();
//			try {
//				finishTime.setTime(sdf.parse(detailArr[7]));
//			} catch (ParseException e) {
//			}
//			record.setFinishTime(finishTime);
//			records.add(record);
//		}
//		
//		for(AliWithdrawReturnRecord record:records){
//			System.out.println(record.getWithdrawOrderNo()+"-"+record.getWithdrawAccountNo()+"-"+record.getUserName()+"-"+record.getAmount()+"-"+record.getFlag()+"-"+record.getRemark()+"-"+"-"+record.getAliOrderNo()+"-"+sdf.format(record.getFinishTime().getTime()));
//		}
	}
	
	
	
	
}
